package wowraidmanager.client.wishlist.news;

import java.util.ArrayList;
import java.util.Date;

import wowraidmanager.client.BaseComposite;
import wowraidmanager.client.service.wishlist.news.NewslistService;
import wowraidmanager.client.service.wishlist.news.NewslistServiceAsync;
import wowraidmanager.client.wishlist.utils.CheckError;
import wowraidmanager.shared.model.wishlist.Newslist;
import wowraidmanager.shared.model.wishlist.UserStatus;

import com.google.appengine.api.datastore.Text;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class News extends BaseComposite{

    private static NewsUiBinder uiBinder = GWT.create(NewsUiBinder.class);

    protected NewslistServiceAsync newslistService = GWT.create(NewslistService.class);

    interface NewsUiBinder extends UiBinder<Widget, News>{
    }

    UserStatus userStatus;

    ArrayList<Newslist> newslistList;

    @UiField
    Label titleLabel;

    @UiField
    Label contentLabel;

    @UiField
    TextBox title;

    @UiField
    RichTextArea content;

    @UiField
    Button saveButton;

    @UiField
    Button newButton;

    @UiField
    Hidden contentKey;

    @UiField
    FlowPanel mainPanel;

    public News(UserStatus userStatus){
        initWidget(uiBinder.createAndBindUi(this));
        this.userStatus = userStatus;
        setContent();
        setButton();
        setNewslist();
    }

    private void setNewslist(){
        newslistService.getNewslist(new AsyncCallback<ArrayList<Newslist>>(){

            public void onSuccess(ArrayList<Newslist> result){
                newslistList = result;
                setMainPanel();
            }

            public void onFailure(Throwable caught){
                clearInfoMessage();
                setErrorMessage("Newsの取得に失敗しました。");
            }
        });
    }

    private void setButton(){
        newButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setContentVisible(true);
                setClearContent();
            }
        });

        saveButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setSaveContent();
            }
        });
    }

    protected void setClearContent(){
        title.setText("");
        content.setHTML("");
        contentKey.setValue("");
    }

    protected void setSaveContent(){
        String titleString = title.getText();
        Text contentText = new Text(content.getHTML());
        String keyString = contentKey.getValue();

        errorString = CheckError.checkNews(titleString, contentText);

        if(errorString.equals("")){
            Newslist newslist;
            if(keyString.equals("")){
                newslist = new Newslist();
            }else{
                newslist = getSelectNewslist(keyString);
            }

            newslist.setTitle(titleString);
            newslist.setText(contentText);
            newslist.setCreator(userStatus.getMember().getMemberName());

            if(newslist.getCreateDate() == null){
                newslist.setCreateDate(new Date());
            }

            newslistService.setNewslist(newslist, new AsyncCallback<Void>(){

                public void onSuccess(Void result){
                    setInfoMessage("Newsの更新に成功しました。");
                    clearErrorMessage();
                    setContentVisible(false);
                    setNewslist();
                }

                public void onFailure(Throwable caught){
                    clearInfoMessage();
                    setErrorMessage("Newsの更新に失敗しました。");
                }
            });
        }else{
            clearInfoMessage();
            setErrorMessage(errorString);
        }
    }

    private Newslist getSelectNewslist(String keyString){
        for(Newslist newslist:newslistList){
            if(newslist.getKey().toString().equals(keyString)){
                return newslist;
            }
        }
        return new Newslist();
    }

    protected void setContentVisible(boolean visible){
        titleLabel.setVisible(visible);
        contentLabel.setVisible(visible);
        title.setVisible(visible);
        content.setVisible(visible);
        saveButton.setVisible(visible);
    }

    private void setMainPanel(){
        ArrayList<FlexTable> newsTableList = setNewsTableList();

        mainPanel.clear();

        for(FlexTable newsTable:newsTableList){
            mainPanel.add(newsTable);
        }
    }

    private ArrayList<FlexTable> setNewsTableList(){
        ArrayList<FlexTable> newsTableList = new ArrayList<FlexTable>();
        for(Newslist newslist:newslistList){
            FlexTable newsTable = new FlexTable();

            newsTable.setStyleName("newsTable");
            newsTable.setWidth("60%");
            newsTable.setCellSpacing(10);

            newsTable.setWidget(0, 0, new Label(newslist.getTitle()));
            newsTable.getCellFormatter().setWidth(0, 0, "40%");

            DateTimeFormat formatter = DateTimeFormat.getFormat("yyyy/MM/dd HH:mm");
            String value = formatter.format(newslist.getCreateDate());
            newsTable.setWidget(0, 1, new Label(value));
            newsTable.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_RIGHT);

            newsTable.setWidget(1, 0, new HTML(newslist.getText().getValue()));
            newsTable.getFlexCellFormatter().setColSpan(1, 0, 2);

            newsTable.setWidget(2, 0, new Hidden("hiddenKey", newslist.getKey().toString()));
            newsTable.getCellFormatter().setWidth(0, 0, "40%");

            newsTable.setWidget(2, 1, new Label(newslist.getCreator()));
            newsTable.getCellFormatter().setHorizontalAlignment(2, 1, HasHorizontalAlignment.ALIGN_RIGHT);

            if(userStatus.isAdmin()){
                Button editButton = new Button("Edit");
                Button deleteButton = new Button("Delete");

                setAdminButton(editButton, deleteButton, newslist);

                newsTable.setWidget(3, 1, editButton);
                newsTable.getCellFormatter().setHorizontalAlignment(3, 1, HasHorizontalAlignment.ALIGN_RIGHT);

                newsTable.setWidget(4, 1, deleteButton);
                newsTable.getCellFormatter().setHorizontalAlignment(4, 1, HasHorizontalAlignment.ALIGN_RIGHT);
            }

            newsTableList.add(newsTable);

        }
        return newsTableList;
    }

    private void setAdminButton(Button editButton, Button deleteButton, final Newslist newslist){
        editButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setEdit(newslist);
            }
        });

        deleteButton.addClickHandler(new ClickHandler(){

            public void onClick(ClickEvent event){
                setDelete(newslist);
            }
        });
    }

    protected void setEdit(Newslist newslist){
        setContentVisible(true);
        title.setText(newslist.getTitle());
        content.setHTML(newslist.getText().getValue());
        contentKey.setValue(newslist.getKey().toString());
    }

    private void setContent(){
        if(userStatus.isAdmin()){
            newButton.setVisible(true);
        }
    }


    protected void setDelete(Newslist newslist){
        new DeleteDialog(newslist, this).show();
    }

    private class DeleteDialog extends DialogBox{
        public DeleteDialog(final Newslist newslist, News news){
            setText("Delete Dialog");
            setAnimationEnabled(true);
            setGlassEnabled(true);

            HTMLPanel content = new HTMLPanel("");
            Label deleteLabel = new Label("本当に以下のNewsを削除しますか？");
            Label newsLabel = new Label("Title:" + newslist.getTitle());

            Button okButton = new Button("OK");
            okButton.addClickHandler(new ClickHandler(){
                public void onClick(ClickEvent event){
                    DeleteDialog.this.hide();
                    deleteNewsDialog(newslist);
                }
            });

            Button cancelButton = new Button ("Cancel");
            cancelButton.addClickHandler(new ClickHandler(){
                public void onClick(ClickEvent event){
                    DeleteDialog.this.hide();
                }
            });

            content.add(deleteLabel);
            content.add(newsLabel);
            content.add(okButton);
            content.add(cancelButton);
            add(content);

            setPopupPosition(news.getOffsetWidth() / 2 - content.getOffsetWidth(), news.getOffsetHeight() / 2);
        }

        protected void deleteNewsDialog(Newslist newslist){
           deleteNews(newslist);
        }
    }

    public void deleteNews(final Newslist newslist){
        newslistService.deleteNewsbyKey(newslist.getKey().toString(), new AsyncCallback<Void>(){

            public void onSuccess(Void result){
                setInfoMessage("News\"" + newslist.getTitle() + "\"を削除しました。");
                clearErrorMessage();
                setNewslist();
            }

            public void onFailure(Throwable caught){
                clearInfoMessage();
                setErrorMessage("News削除に失敗しました。");
            }
        });
    }
}
